#pragma once

#include <vex/policy/empty_base.h>

namespace vex { namespace policy {
    template <class TClass = nothing, class TClassTraits = nothing, class TBase = empty_base>
    class empty_policy;

    template <class TClass = nothing, class TClassTraits = nothing, class TBase = empty_base,
        template <class, class, class> class TClass1 = empty_policy,
        template <class, class, class> class TClass2 = empty_policy,
        template <class, class, class> class TClass3 = empty_policy,
        template <class, class, class> class TClass4 = empty_policy,
        template <class, class, class> class TClass5 = empty_policy,
        template <class, class, class> class TClass6 = empty_policy,
        template <class, class, class> class TClass7 = empty_policy,
        template <class, class, class> class TClass8 = empty_policy
    > struct merge_policies;

    template <class T, class TClassTraits, class TBase,
        template <class, class, class> class TClass1
    > struct merge_policies<T, TClassTraits, TBase,
    TClass1, 
    empty_policy, 
    empty_policy, 
    empty_policy, 
    empty_policy, 
    empty_policy, 
    empty_policy, 
    empty_policy
    > 
    {
        typedef TClass1< T, TClassTraits, 
            TBase > type;
    };

    template <class T, class TClassTraits, class TBase,
        template <class, class, class> class TClass1,
        template <class, class, class> class TClass2
    > struct merge_policies<T, TClassTraits, TBase,
    TClass1, 
    TClass2, 
    empty_policy, 
    empty_policy,
    empty_policy,
    empty_policy, 
    empty_policy,
    empty_policy
    > 
    {
        typedef TClass1< T, TClassTraits, 
            TClass2< T, TClassTraits, 
            TBase > > type;
    };

    template <class T, class TClassTraits, class TBase,
        template <class, class, class> class TClass1,
        template <class, class, class> class TClass2,
        template <class, class, class> class TClass3
    > struct merge_policies<T, TClassTraits, TBase,
    TClass1, 
    TClass2, 
    TClass3, 
    empty_policy,
    empty_policy,
    empty_policy, 
    empty_policy,
    empty_policy
    > 
    {
        typedef TClass1< T, TClassTraits, 
            TClass2< T, TClassTraits, 
            TClass3< T, TClassTraits, 
            TBase > > > type;
    };

    template <class T, class TClassTraits, class TBase, 
        template <class, class, class> class TClass1,
        template <class, class, class> class TClass2,
        template <class, class, class> class TClass3,
        template <class, class, class> class TClass4
    > struct merge_policies<T, TClassTraits, TBase,
    TClass1, 
    TClass2, 
    TClass3, 
    TClass4,
    empty_policy,
    empty_policy, 
    empty_policy,
    empty_policy
    > 
    {
        typedef TClass1< T, TClassTraits, 
            TClass2< T, TClassTraits, 
            TClass3< T, TClassTraits,
            TClass4< T, TClassTraits,
            TBase > > > > type;
    };

    template <class T, class TClassTraits, class TBase,
        template <class, class, class> class TClass1,
        template <class, class, class> class TClass2,
        template <class, class, class> class TClass3,
        template <class, class, class> class TClass4,
        template <class, class, class> class TClass5
    > struct merge_policies<T, TClassTraits, TBase,
    TClass1, 
    TClass2, 
    TClass3, 
    TClass4,
    TClass5,
    empty_policy, 
    empty_policy,
    empty_policy
    > 
    {
        typedef TClass1< T, TClassTraits, 
            TClass2< T, TClassTraits, 
            TClass3< T, TClassTraits,
            TClass4< T, TClassTraits,
            TClass5< T, TClassTraits,
            TBase > > > > > type;
    };

    template <class T, class TClassTraits, class TBase,
        template <class, class, class> class TClass1,
        template <class, class, class> class TClass2,
        template <class, class, class> class TClass3,
        template <class, class, class> class TClass4,
        template <class, class, class> class TClass5,
        template <class, class, class> class TClass6
    > struct merge_policies<T, TClassTraits, TBase,
    TClass1, 
    TClass2, 
    TClass3, 
    TClass4,
    TClass5,
    TClass6, 
    empty_policy,
    empty_policy
    > 
    {
        typedef TClass1< T, TClassTraits, 
            TClass2< T, TClassTraits, 
            TClass3< T, TClassTraits,
            TClass4< T, TClassTraits,
            TClass5< T, TClassTraits,
            TClass6< T, TClassTraits,
            TBase > > > > > > type;
    };
}}